<!--
    @Title: LoaderIfc
    @Author  dudalei
    @Package
    @Date  2024/11/7 下午8:11
    @description:
-->
<script setup lang="ts">
import { inject, onBeforeUnmount, ref, watch } from 'vue'
import { useThreeSceneInjectKey } from '@/components/ThreeScene/common/useInjectKeys'
import { IFCLoader } from 'web-ifc-three'
import { IFCSPACE } from 'web-ifc'
import {
  AmbientLight,
  BufferAttribute,
  BufferGeometry,
  Mesh,
  MeshBasicMaterial,
  Vector3,
} from 'three'
import type { intersectObjectsType } from '@/components/ThreeScene/common/ThreeScene'
import type { IFCModel } from 'web-ifc-three/IFC/components/IFCModel'
import { ElLoading } from 'element-plus'

// 注入threeScene
const threeScene = inject(useThreeSceneInjectKey)

// 接收参数
const props = defineProps<{
  // ifc地址
  url: string
}>()

const selectBox = 'select-box'
/**
 * 根据材质下标创建 box
 * @param object
 * @param materialIndex
 */
const createBox = async (object: IFCModel, materialIndex: number) => {
  const { requestRenderIfNotRequested, scene } = threeScene!.value!
  scene.getObjectByName(selectBox)?.remove()
  const { attributes, groups } = object.geometry
  const geometry = new BufferGeometry()
  const verticesArray: number[] = []
  // 找出当前点击材质的所有三角面片
  for (let i = 0; i < groups.length; i++) {
    const group = groups[i]
    // 如果不是点击的材质就返回
    if (group.materialIndex !== materialIndex) {
      continue
    }
    const start = group.start
    const count = group.count

    const { position } = attributes
    for (let j = start; j < start + count; j++) {
      verticesArray.push(position.array[j])
    }
  }

  // 创建一个简单的矩形. 在这里我们左上和右下顶点被复制了两次。
  // 因为在两个三角面片里，这两个顶点都需要被用到。
  const vertices = new Float32Array(verticesArray)

  // itemSize = 3 因为每个顶点都是一个三元组。
  geometry.setAttribute('position', new BufferAttribute(vertices, 3))
  const material = new MeshBasicMaterial({ color: 0xff0000, opacity: 0.5 })
  const mesh = new Mesh(geometry, material)
  mesh.name = selectBox
  mesh.renderOrder = 10000
  scene.add(mesh)
  requestRenderIfNotRequested()
}

// 折叠面板选择的名字
const collapseNames = ref<string[]>([])
// 属性数据
const propertySets = ref<{ title: string; data: { title: string; value: string }[] }[]>([])
// 场景点击事件回调
const clickCallback = (intersects: intersectObjectsType[]) => {
  console.log('点击事件触发了')
  // 选择的物体
  const intersect = intersects[0]
  // 得到材质的下标
  const materialIndex = intersect.face!.materialIndex
  // 得到选择的模型
  const model = intersect.object as IFCModel
  // createBox(model, materialIndex)
  // model.material[materialIndex].color = new Color('#f35050')
  // threeScene!.value!.requestRenderIfNotRequested()
  // 得到点击的面的下标
  const faceIndex = intersect.faceIndex as number
  // 获取物体的 Express ID
  const expressId = ifcLoader.ifcManager.getExpressId(model.geometry, faceIndex)
  console.log('expressId', expressId)
  /* ifcLoader.ifcManager.getItemProperties(model.modelID, expressId, true).then((res) => {
    console.log('getItemProperties', res)
  })*/
  ifcLoader.ifcManager.getPropertySets(model.modelID, expressId, true).then((res) => {
    // console.log('getPropertySets', res)
    collapseNames.value = []
    propertySets.value = res.map((item) => {
      // HasPropertie
      const data = item.HasProperties.map((item) => {
        return {
          title: item.Name.value,
          value: item.NominalValue,
        }
      })
      collapseNames.value.push(item.Name.value)
      return {
        title: item.Name.value,
        data,
      }
    })
  })
  // model.ifcManager.getExpressId()
}
//Setup IFC Loader
const ifcLoader = new IFCLoader()

const initTree = (model: IFCModel) => {
  if (!model.ifcManager) {
    return
  }
  // 获取给定元素的本机属性
  /* ifcLoader.ifcManager.getItemProperties(model.modelID, 137858).then((res) => {
    console.log('getItemProperties', res)
  })*/
  // 获取所有类型数据
  /* ifcLoader.ifcManager
    .getAllItemsOfType(model.modelID, IFCPROPERTYSINGLEVALUE, true)
    .then((res) => {
      console.log('getAllItemsOfType', res)
    })*/
}

/**
 * 延迟函数
 * @param time
 */
const delayTimer = async (time: number = 10) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(true)
    }, time)
  })
}
/**
 * 初始化
 */
const init = async () => {
  const loading = ElLoading.service({
    lock: true,
    text: '正在加载中请稍后!',
    background: 'rgba(0, 0, 0, 0.7)',
  })
  await delayTimer()
  console.time('加载时间')
  const { scene, requestRenderIfNotRequested, camera, controls } = threeScene!.value!

  // web-ifc 在public下面
  await ifcLoader.ifcManager.setWasmPath('/ifc/web-ifc/')

  await ifcLoader.ifcManager.parser.setupOptionalCategories({
    [IFCSPACE]: false,
    // [IFCOPENINGELEMENT]: false,
  })

  await ifcLoader.ifcManager.applyWebIfcConfig({
    USE_FAST_BOOLS: true,
  })
  const center = new Vector3(1068.4822387695312, 17.23204231262207, 8145.7236328125)
  ifcLoader.load(props.url, (model) => {
    // model.ifcManager.getExpressId()
    scene.add(model)
    console.log('模型加载完成:')
    initTree(model)
    // 请求更新场景
    // requestRenderIfNotRequested()
    // model.updateMatrixWorld()
    // requestRenderIfNotRequested()
    // 设置摄像机以框住长方体
    // frameArea(model, 0.5, 6, controls, camera, new Vector3(0, 250, 0))

    camera.position.set(901.0298344347193, 172.1991982414637, 8177.930785651204)
    camera.lookAt(center.x, center.y, center.z)
    controls.target.copy(center)
    controls.update()
    // const directionalLight1 = new DirectionalLight(0xffeeff, 3)
    // directionalLight1.position.set(901.0298344347193, 172.1991982414637, 8177.930785651204)
    // directionalLight1.target = model
    // scene.add(directionalLight1)
    /* window.getPos = () => {
      console.log('camera', camera)
      console.log('controls.target', controls.target)
    }*/
    requestRenderIfNotRequested()

    loading.close()
    console.timeEnd('加载时间')
  })

  //Lights
  //
  // const directionalLight2 = new DirectionalLight(0xffffff, 3)
  // directionalLight2.position.set(-1000, 200, 8177)
  // scene.add(directionalLight2)

  const ambientLight = new AmbientLight(0xffffff, 4)
  scene.add(ambientLight)
}
// 监听threeScene是否注入成功
watch(
  threeScene!,
  () => {
    if (!threeScene || !threeScene.value) {
      return
    }
    console.log('初始化init')
    init()
    threeScene.value.clickCallback(clickCallback)
  },
  {
    immediate: true,
  },
)
onBeforeUnmount(() => {
  ifcLoader.ifcManager.dispose()
})
</script>

<template>
  <div class="property-sets">
    <el-collapse v-model="collapseNames">
      <el-collapse-item
        v-for="item in propertySets"
        :title="item.title"
        :name="item.title"
        :key="item.title"
      >
        <el-descriptions class="margin-top" :column="1" size="small" border>
          <el-descriptions-item v-for="(data, index) in item.data" :key="index">
            <template #label>
              {{ data.title }}
            </template>
            {{ data.value }}
          </el-descriptions-item>
        </el-descriptions>
      </el-collapse-item>
    </el-collapse>
  </div>
</template>

<style scoped>
.property-sets {
  position: absolute;
  z-index: 2;
  top: 0;
  right: 0;
  width: 300px;
  height: 100%;
  overflow: auto;
  background-color: #2f2f2f;

  :deep(.el-descriptions__body) {
    overflow: auto;
  }
}
</style>
